<template>
  <el-dialog
    :before-close="handleClose"
    :close-on-click-modal="false"
    title="创建新排除规则"
    :visible.sync="dialogVisible"
  >
    <el-form
      ref="ruleForm"
      v-loading="loading"
      label-width="100px"
      :model="ruleForm"
      :rules="rules"
      size="mini"
      style="margin-left: -5%;"
    >
      <div
        style="display: flex; align-items: center; justify-content:flex-start;"
      >
        <el-form-item label="规则名" prop="name" style="width: 50%;">
          <el-input
            v-model="ruleForm.name"
            placeholder="请输入规则名"
            spellcheck="false"
          />
        </el-form-item>
        <el-form-item label="排除阻断" prop="block">
          <el-switch
            v-model="ruleForm.block"
            size="mini"
            @change="handleBlockChange($event, ruleForm)"
          />
        </el-form-item>
      </div>

      <div
        style="display: flex; align-items: center; justify-content: flex-start;"
      >
        <el-form-item
          v-permission="['super', 'org']"
          label="创建者"
          prop="user_id"
          style="width: 50%;"
        >
          <el-select v-model="ruleForm.user_id" filterable>
            <el-option
              v-for="(item, index) in userList"
              :key="index"
              :label="`${item.last_name}${item.first_name} (${item.email})`"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="初始状态" prop="disabled">
          <el-switch v-model="ruleForm.disabled" size="mini" />
        </el-form-item>
      </div>

      <div>
        <el-form-item v-permission="['super']" label="公共" prop="public">
          <el-switch v-model="ruleForm.public" />
        </el-form-item>
      </div>

      <el-form-item label="规则描述" prop="abstract">
        <el-input
          v-model="ruleForm.abstract"
          :autosize="{ minRows: 3, maxRows: 20 }"
          spellcheck="false"
          type="textarea"
        />
      </el-form-item>
    </el-form>
    <el-tabs type="border-card">
      <el-tab-pane label="简易模式">
        <el-card
          v-for="(domain, index) in domains"
          :key="index"
          :model="domain"
          style="margin: 0;"
        >
          <el-form
            ref="domain"
            v-loading="loading"
            label-width="80px"
            :model="domain.property"
            :rules="propertyRules"
            size="mini"
          >
            <div
              style="display: flex; align-items: flex-end; justify-content: space-between; margin-left: -6%; margin-top: -1%;"
            >
              <el-form-item label="属性" size="mini">
                <el-select
                  v-model="domain.keyword"
                  filterable
                  size="mini"
                  @change="handleChange(index)"
                >
                  <el-option
                    v-for="(item, kwindex) in keywordList"
                    v-show="selectableKeywordValueList.includes(item.value)"
                    :key="kwindex"
                    :label="`${item.name}`"
                    :value="`${item.value}`"
                    @click.native="loadingKeywordProp(item.value, domain)"
                  />
                </el-select>
              </el-form-item>
              <el-form-item
                v-if="!domain.property.simple"
                label="匹配方式"
                prop="match"
                size="mini"
              >
                <el-select
                  v-model="domain.property.match"
                  filterable
                  size="mini"
                  @change="handleChange(index)"
                >
                  <el-option
                    v-for="(item, mlindex) in domain.property.matchList"
                    :key="mlindex"
                    :label="item.name"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item
                v-if="!domain.property.simple"
                id="text"
                label="条件不匹配"
                label-width="100px"
                size="mini"
              >
                <el-switch
                  v-model="domain.property.noCondition"
                  size="mini"
                  @change="handleChange(index)"
                />
              </el-form-item>
            </div>
            <div
              style="display: flex; align-items: center; justify-content:space-between;"
            >
              <el-form-item
                v-if="
                  !domain.propertyInputOption.isSelect &&
                    domain.propertyInputOption.inputType != 'bool' &&
                    domain.keyword != ''
                "
                label="值"
                prop="value"
                style="margin-left: -8%; margin-bottom: 0%;"
              >
                <el-input
                  v-model="domain.property.value"
                  :autosize="{ minRows: 3, maxRows: 20 }"
                  size="mini"
                  spellcheck="false"
                  :type="domain.propertyInputOption.inputType"
                  @input="handleChange(index)"
                />
              </el-form-item>
              <el-form-item
                v-if="
                  domain.propertyInputOption.isSelect &&
                    !domain.propertyInputOption.isAllowCreate
                "
                label="值"
                prop="value"
                style="margin-left: -8%; margin-bottom: 0%;"
              >
                <el-select
                  :key="domain.keyword"
                  v-model="domain.property.value"
                  filterable
                  :multiple="domain.propertyInputOption.isMultiple"
                  size="mini"
                >
                  <el-option
                    v-for="(item, vlindex) in domain.property.valueList"
                    :key="vlindex"
                    :label="item.name"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item
                v-if="
                  domain.propertyInputOption.isSelect &&
                    domain.propertyInputOption.isAllowCreate
                "
                label="值"
                prop="value"
                style="margin-left: -8%; margin-bottom: 0%;"
              >
                <el-select
                  :key="domain.keyword"
                  v-model="domain.property.value"
                  allow-create
                  filterable
                  :multiple="domain.propertyInputOption.isMultiple"
                  size="mini"
                >
                  <el-option
                    v-for="(item, vlindex) in domain.property.valueList"
                    :key="vlindex"
                    :label="item.name"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item
                v-if="domain.propertyInputOption.inputType == 'bool'"
                label="值"
                prop="value"
                style="margin-left: -8%; margin-bottom: 0%;"
              >
                <el-switch v-model="domain.property.value" size="mini" />
                {{ domain.property.value }}
              </el-form-item>
              <el-button plain size="mini" @click="removeDomain(domain)"
                >删除</el-button
              >
            </div>
          </el-form>
        </el-card>

        <div style="margin-top: 5px;margin-left: 5px;">
          <el-button
            v-if="
              domains.length == 0 || domains[domains.length - 1].keyword != ''
            "
            plain
            size="mini"
            type="success"
            @click="addDomain()"
            >新增条件 +</el-button
          >
          <el-button plain size="mini" @click="toExpertModeBtn()"
            >同步至专家模式 >></el-button
          >
        </div>
      </el-tab-pane>
      <el-tab-pane label="专家模式">
        <el-form
          ref="ruleForm"
          v-loading="loading"
          label-width="100px"
          :model="ruleForm"
          :rules="rules"
          size="mini"
        >
          <el-form-item label="规则定义" prop="rule_dict">
            <el-input
              v-model="ruleForm.rule_dict"
              :autosize="{ minRows: 3, maxRows: 20 }"
              spellcheck="false"
              type="textarea"
            />
          </el-form-item>
        </el-form>
      </el-tab-pane>
    </el-tabs>
    <div
      style="display: flex; align-items: center; justify-content:center; margin-top: 10px;"
    >
      <el-button type="primary" @click="submit('ruleForm')">保存</el-button>
      <el-button @click="dialogVisible = false">返回</el-button>
    </div>
  </el-dialog>
</template>

<script>
import clearWatch from "@/utils/mixin/clearWatch";
import user from "@/api/user";
import rule from "@/api/rule/exclude";
import { mapGetters } from "vuex";
export default {
  name: "ToastNewRule",
  mixins: [clearWatch],
  data() {
    return {
      dialogVisible: false,
      loading: false,
      org_id: "",
      userList: [],
      techniqueList: [],
      severityList: [],
      scenarioList: [],
      keywordList: [],
      selectableKeywordValueList: [],
      domains: [
        {
          keyword: "",
          property: {
            noCondition: false,
            match: "",
            matchList: [],
            value: "",
            simple: true,
            valueType: "string",
            valueList: [],
            isNumberic: false
          },
          propertyInputOption: {
            isSelect: false,
            isMultiple: false,
            isAllowCreate: false
          }
        }
      ],
      ruleForm: {
        name: "",
        user_id: "",
        severity_id: "",
        scenario_id: "",
        technique_id: "",
        disabled: false,
        block: false,
        public: false,
        rule_dict: "",
        abstract: ""
      },
      rules: {
        name: [{ required: true, message: "请输入规则名", trigger: "blur" }],
        rule_dict: [
          {
            required: true,
            validator: (rule, value, callback) => {
              const isJSON = str => {
                if (typeof str == "string") {
                  try {
                    const obj = JSON.parse(str);
                    if (typeof obj == "object" && obj) {
                      return true;
                    } else {
                      return false;
                    }
                  } catch (e) {
                    return false;
                  }
                }
              };
              if (!value) {
                return callback(new Error("请输入规则定义"));
              }
              if (!isJSON(value)) {
                return callback(new Error("请输入正确的JSON"));
              }
              callback();
            },

            trigger: "blur"
          }
        ],
        abstract: [
          { required: true, message: "请输入排除规则描述", trigger: "blur" }
        ],
        user_id: [
          { required: true, message: "请选择创建者", trigger: "change" }
        ],
        disabled: [
          { required: true, message: "请选择初始状态", trigger: "change" }
        ],
        block: [
          { required: true, message: "请选择阻断状态", trigger: "change" }
        ],
        public: [
          { required: true, message: "请选择公共状态", trigger: "change" }
        ]
      },
      propertyRules: {
        value: [{ required: true, message: "请输入值", trigger: "blur" }],
        match: [{ required: true, message: "请选择匹配方式", trigger: "blur" }]
      }
    };
  },
  computed: mapGetters(["UserInfo"]),
  methods: {
    handleClose(done) {
      done();
    },
    show(org_id) {
      this.dialogVisible = !this.dialogVisible;

      this.org_id = org_id;
      this.loadingData();
    },
    async loadingData() {
      if (this.UserInfo.role_en === "user") {
        this.ruleForm.user_id = this.UserInfo.id;
      } else {
        await this.loadingUser();
      }
      await this.loadingKeyword();
    },
    loadingUser() {
      return user.users({ org_id: this.org_id }).then(res => {
        this.userList = res.data.users;
      });
    },
    loadingKeyword() {
      var keywordList = [];
      return rule
        .getKeyword({
          block: this.ruleForm.block,
          keyword_list: keywordList
        })
        .then(res => {
          this.keywordList = res.data.spec;
          res.data.spec.forEach(item => {
            this.selectableKeywordValueList.push(item.value);
          });
        });
    },
    loadingSelectableKeywordValue() {
      var keywordList = [];
      this.domains.forEach(domain => {
        if (domain.keyword != "") keywordList.push(domain.keyword);
      });
      return rule
        .getKeyword({
          block: this.ruleForm.block,
          keyword_list: keywordList
        })
        .then(res => {
          this.selectableKeywordValueList = [];
          res.data.spec.forEach(item => {
            this.selectableKeywordValueList.push(item.value);
            var hasKeyword = false;
            this.keywordList.forEach(item1 => {
              if (JSON.stringify(item1) == JSON.stringify(item)) {
                hasKeyword = true;
              }
            });
            if (!hasKeyword) {
              this.keywordList.push(item);
            }
          });
        });
    },
    loadingKeywordProp(keyword, domain) {
      this.loadingSelectableKeywordValue();
      //console.log(this.domains);
      domain.property.value = undefined;
      //console.log("loadingKeywordProp");
      return rule
        .getKeywordProp({
          keyword: keyword
        })
        .then(res => {
          var property = res.data.property;
          domain.property.matchList = property.match_list;
          domain.property.simple = property.simple;
          domain.property.valueList = property.value_list;
          domain.property.isNumberic = false;
          //console.log(property.value_list);
          const splitedValueType = property.value_type.split("_");
          domain.propertyInputOption.isSelect = false;
          domain.propertyInputOption.isMultiple = false;
          domain.propertyInputOption.isAllowCreate = false;
          domain.propertyInputOption.inputType = "";
          const spLast = splitedValueType[splitedValueType.length - 1];
          const spBegin = splitedValueType[0];
          if (property.value_list == undefined) {
            domain.propertyInputOption.isAllowCreate = true;
          }
          if (property.value_type.indexOf("number") != -1) {
            domain.property.isNumberic = true;
          }
          if (spBegin == "multi") {
            setTimeout(() => {
              domain.propertyInputOption.isSelect = true;
              domain.propertyInputOption.isMultiple = true;
            });
            return;
          }
          if (spLast == "list") {
            setTimeout(() => {
              domain.propertyInputOption.isSelect = true;
            });
            return;
          }
          domain.propertyInputOption.inputType = splitedValueType[0];
          if (domain.propertyInputOption.inputType == "bool")
            domain.property.value = false;
        });
    },
    removeDomain(item) {
      var index = this.domains.indexOf(item);
      if (index !== -1) {
        this.domains.splice(index, 1);
      }
      this.loadingSelectableKeywordValue();
    },
    handleChange(index) {
      // 获取当前域名的值
      const value = this.domains[index].value;

      // 更新数据模型对象的对应属性值
      this.domains[index].value = value;
    },
    handleBlockChange(value, ruleForm) {
      let judge =
        "修改规则类型将完全清空当前规则定义！请确认是否继续修改规则类型？";
      this.$confirm(judge, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.domains = [];
          this.ruleForm.rule_dict = "{}";
          this.$notify.info({
            title: "修改成功",
            message: "请重新进行规则定义"
          });
        })
        .catch(() => {
          ruleForm.block = !value;
        });
    },
    addDomain() {
      // 添加新的条件
      this.loadingSelectableKeywordValue();
      this.domains.push({
        keyword: "",
        property: {
          noCondition: false,
          match: "",
          matchList: [],
          value: "",
          simple: true,
          valueType: "string",
          valueList: [],
          isNumberic: false
        },
        propertyInputOption: {
          isSelect: false,
          isMultiple: false,
          isAllowCreate: false
        }
      });
    },
    getJSONDataByDomains() {
      var ret = {};
      this.domains.forEach(item => {
        const domainKey = item.keyword;
        const property = item.property;
        var domainValue;
        if (domainKey != "") {
          if (property.isNumberic) {
            if (typeof property.value == "object") {
              property.value = property.value.map(Number);
            } else if (typeof property.value == "string") {
              property.value = Number(property.value);
            }
          }
          if (property.simple) {
            domainValue = property.value;
          } else {
            domainValue = {
              Bool: !property.noCondition,
              Match: property.match,
              Value: property.value
            };
          }
          ret[domainKey] = domainValue;
        }
      });
      return ret;
    },
    toExpertMode() {
      this.ruleForm.rule_dict = JSON.stringify(
        this.getJSONDataByDomains(),
        null,
        4
      );
    },
    toExpertModeBtn() {
      this.toExpertMode();
      this.$notify.info({
        title: "同步成功",
        message: "您可以切换至专家模式查看原始规则"
      });
    },
    submit(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          let data = Object.assign({}, this.ruleForm);
          data.rule_dict = JSON.parse(data.rule_dict);
          data.disabled = !data.disabled;
          rule.create(data).then(res => {
            this.$message.success(res.data.message);
            this.dialogVisible = false;
            this.domains = [];
            this.$emit("change");
          });
        } else {
          return false;
        }
      });
    }
  }
};
</script>
<style lang="scss" scoped>
#text {
  width: 130px;
}
#del {
  position: absolute;
  bottom: 3px;
  right: 2px;
}
#val {
  width: 90%;
}
::v-deep
  .el-form-item.is-required:not(.is-no-asterisk)
  > .el-form-item__label:before {
  content: " ";
  width: 0px;
  margin-right: 0px;
}
</style>
